package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @author 韩先楚
 */
@Component
@Aspect
@Slf4j
public class AutoFillAspect {



    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)" )
    public void autoFill() {}

    /**
     * 前置通知，在目标方法执行前填充参数
     * @param joinPoint
     * @throws Throwable
     */
    @Before("autoFill()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
         log.info("前置通知：参数自动填充");
         //获取到被拦截方法什上面的注解的的属性值
        MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取连接点的方法签名
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);// 获取方法的注解对象
        OperationType value = autoFill.value();// 获取注解的属性值

        //获取到方法参数-对象
        Object[] args = joinPoint.getArgs();
        if (args==null || args.length==0)
        {
            return;
        }

        //获取对象
        Object arg = args[0];

        //准备需要赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long id = BaseContext.getCurrentId();

        //根据不同的操作类型,给对象赋值
        if (value == OperationType.INSERT)
        {
            //插入操作
             arg.getClass().getMethod("setCreateTime", LocalDateTime.class).invoke(arg, now);
             arg.getClass().getMethod("setCreateUser", Long.class).invoke(arg, id);
             arg.getClass().getMethod("setUpdateTime", LocalDateTime.class).invoke(arg, now);
            arg.getClass().getMethod("setUpdateUser", Long.class).invoke(arg, id);

        } else
        {
            //更新操作
            arg.getClass().getMethod("setUpdateTime", LocalDateTime.class).invoke(arg, now);
            arg.getClass().getMethod("setUpdateUser", Long.class).invoke(arg, id);
        }

    }

}
